<?php
/**
 * User: hjd-yao
 * Date: 2019/1/28
 * Time: 17:31
 */

namespace App\Helpers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\HtmlString;

class Search
{
    public $searchAction;
    public $searchModel;
    public $request;


    public $textSearch = [];
    public $selectSearch = [];

    public $_searchName = [];
    protected $_searchType = [];
    protected $_fields = [];
    protected $default = [];

    protected $_symbol = []; //格式：['搜索项name'=>'=|>=|<=|>|<|like']
    public $relationFields;
    public $_reply = [];
    public $_removes = [];


    public $_replace = [];

    private $searchData = [];


    public  function __construct(Request $request){
        $this->searchAction = URL::current();
        $this->request = $request;
        $this->default = $request->input();
    }
    public function __call($method, $arguments)
    {
        throw new \Exception($method.'不存在');
    }

    public static function make(Request $request)
    {
        return new static($request);
    }

    public function bindModel($model)
    {
        $this->searchModel = $model;
        return $this;
    }

    public function action($url = null)
    {
        $url = empty($url)?url()->full():$url;
        $this->searchAction = $url;
        return $this;
    }

    public function relationModel($relations)
    {
        foreach ($relations as $field=>$callback) {
            $this->relationFields[] = $field;
            if(isset($this->searchData[$field])){
                $data = $this->searchData[$field];
                $this->searchData[$field] = $callback($data);
            }
        }
        return $this;
    }

    public function input($name,$title,$default='',$arguments = [])
    {
        $default = $this->default[$name]??$default;
        $this->textSearch[$name] = [
            'type'=>'text',
            'name'=>$name,
            'title'=>$title,
            'value'=>$default,
        ];
        $this->_symbol[$name] = $arguments['symbol'] ?? '=';
        $this->setSearchInfo($name,$arguments['field']??$name,'text');
        return $this;

    }

    public function select($name,$title,$options,$default='',$arguments = [])
    {
        $default = $this->default[$name]??$default;
        $this->textSearch[$name] = [
            'type'=>'select',
            'options'=>$options,
            'name'=>$name,
            'title'=>$title,
            'value'=>$default,
        ];
        $this->_symbol[$name] = $arguments['symbol'] ?? '=';
        $this->setSearchInfo($name,$arguments['field']??$name,'select');
        return $this;
    }

    public function time($name,$title,$default='',$arguments = [])
    {
        $default = $this->default[$name]??$default;
        $this->textSearch[$name] = [
            'type'=>'time',
            'name'=>$name,
            'title'=>$title,
            'value'=>$default,
        ];
        $this->setSearchInfo($name,$arguments['field']??$name,'time');
        return $this;
    }

    private function setSearchInfo($name,$field,$search_type)
    {
        $this->_searchName[] = $name;
        $this->_fields[$name] = $field;
        $this->_searchType[$name] = $search_type;
    }

    public function render($view='backend::public.search')
    {
        return new HtmlString(
            view()->make($view,['search'=>$this])->render()
        );
    }

    public function bindSearchData()
    {
        $this->searchData = array_filter($this->request->only($this->_searchName),function ($v){
            return trim($v)=='' ||strtolower($v) == 'null'||ctype_space($v)?false:true;
        });
        return $this;
    }

    public function where()
    {
        $data = $this->searchData;
        if(!$data){
            return $this->searchModel;
        }
        foreach ($this->textSearch as $name=>$search){
            if(in_array($name,$this->_removes)){
                continue;
            }

            if($search['type'] == 'time'&&isset($data[$name])){
                $data[$name] = str2arr($data[$name],'~');
            }
            $this->filterWhere($name,$data);
        }
        return $this->searchModel;
    }

    /**
     *  合并搜索条件
     * @param $name
     * @param $search_data
     * @return array
     */
    private function filterWhere($name,$search_data)
    {

        if (!isset($search_data[$name])) {
            return [];
        }
        $data= $search_data[$name];

        if($data=='' || $data == '-100' ){
            return [];
        }

        $field=isset($this->_fields[$name])&&!empty($this->_fields[$name])
            ?$this->_fields[$name]:$name;
        if(is_array($field)){
            return [];
        }

        if(!is_array($data)){
            $symbol = $this->_symbol[$name];
            if($symbol == 'like'){
                $data = '%'.$data.'%';
            }
            $this->searchModel = $this->searchModel->where($field,$symbol,$data);
            return true;
        }

        if ($this->_searchType[$name] == 'time') {
            $data = array_map(function($v){ return strtotime($v);},$data);
            if(count($data)<=1){
                $this->searchModel = $this->searchModel->where($field,'>=', $data[0]);
            }
            $this->searchModel = $this->searchModel->whereBetween($field, $data);
            return true;
        } else {
            $this->searchModel = $this->searchModel->whereIn($field, $data);
            return true;
        }
    }

    public function getSearchData()
    {
        return array_filter($this->request->only($this->_searchName),function ($v){
            return trim($v)=='' ||strtolower($v) == 'null'||ctype_space($v)?false:true;
        });
    }
}